--[[
游戏使用一副除去大小王的扑克牌，共4个花色52张牌。

诈金花
1、豹子（AAA最大，222最小）。
2、同花顺（AKQ最大，234最小）。
3、同花（AKJ最大，352最小）。
4、顺子（AKQ最大，234最小）。
5、对子（AAK最大，223最小）。
6、单张（AKJ最大，352最小）。玩“诈金花”可能牌小诈走牌大，是实力、勇气和智谋的较量，是冒险家的游戏。
特殊：花色不同的 235 比豹子大

]]

require "util"

local random = math.random
local table_copy = table.copy

local Rule = class("Rule")

function  Rule:ctor()
	--随机种子
	math.randomseed()
	--扑克牌说明，0xAB, (A为花色 0黑桃 1红心 2草花 3方块)，B为点数1-13为A-K 
	self.card = {
		0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d,
     	0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d,
     	0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d,
     	0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d
	}
	--牌型权重基值 单张，对子，顺子，同花，同花顺，豹子
	self.tbWeight = {danzhang=0x1000,duizi=0x2000,sunzi=0x3000,tonghua=0x4000,tonghuasun=0x5000,baozi=0x6000} 
	--要发的牌
	self.tbCard = {}
	--牌型
	self.tbCardType = {
		[1] = '单张',
		[2] = '对子',
		[3] = '顺子',
		[4] = '同花',
		[5] = '同花顺',
		[6] = '豹子',
	}
end

--洗牌
function Rule:shuffle()	
	for k,v in pairs(self.card) do 
		self.tbCard[k] = v
	end
	table.mix(self.tbCard)
end

--取牌
function Rule:getCard(num)
	local tbRes = {}
	local n = num or 0
	for k,v in pairs(self.tbCard) do 
		if n <= 0 then break end
		if v then 
			n = n-1
			table.insert(tbRes,v)
			self.tbCard[k] = nil
		end
	end
	return tbRes
end

--不同色235
function Rule:special(tbNum)
	local group = {
		{2,3,5},
		{2,5,3},
		{3,5,2},
		{3,2,5},
		{5,3,2},
		{5,2,3},
	}
	local b235 = true
	for k,v in pairs(group) do 
		for i=1,#v do 
			if v[i] ~= tbNum[i] then 
				b235 = false
				break
			end
		end
		if b235 then 
			return true
		end
	end
	return false
end

--豹子
function Rule:baozi(tbNum)
	local card
	for k,v in pairs(tbNum) do 
		if not card then 
			card = v
		end
		--有不一样的牌不是豹子
		if card ~= v then 
			return false
		end
	end
	return true
end

--同花顺
function Rule:tonghuasun(tb,tbNum)
	if self:tonghua(tb) and self:sunzi(tbNum) then 
		return true
	end
	return false
end

--同花
function Rule:tonghua(tb)
	local huase
	for k,v in pairs(tb) do 
		if not huase then 
			huase = v & 0xf0 
		end
		if huase ~= v & 0xf0 then 
			return false
		end
	end
	return true
end

--顺子
function Rule:sunzi(tbNum)
	--AQK 特殊顺子
	if tbNum[1] == 0x01 and tbNum[2] == 0x0c and tbNum[3] == 0x0d then 
		return true,true
	end
	local num
	for k,v in pairs(tbNum) do 
		if not num then 
			num = v 
		elseif v ~= num + 1 then
			return false
		else
			num = v
		end
	end
	return true
end

--对子 
function Rule:duizi(tb)
	-- local arr = {
	-- 	{1,2,3},
	-- 	{1,3,2},
	-- 	{2,3,1},	
	-- }
	if tb[1] == tb[2] or tb[1] == tb[3] then 
		return true,1
	elseif tb[2] == tb[3] then 
		return true,2
	end
	return false
end

--牌的权重
function Rule:getCardWeight(tb)
	print("++___getCardWeight________________",tb)
 	local tbWeight = self.tbWeight --牌型权重基值
 	local tbRes = {card={},weight=0} --返回结果
 	local tbCard = table_copy(tb) --返回牌
 	local tbCardNum = {} --牌值列表
	--local tbCardPoint = {} --牌点数列表

	local maxCard    --最大牌
	local weight = 0 --权重

	for i=1,3 do		
		local cardnum = tb[i] & 0x0f
		table.insert(tbCardNum,cardnum)
		-- --找到最大的牌
		-- if not maxCard then 
		-- 	maxCard = tb[i]
		-- end
		-- if cardnum == 0x01 then --A是最大的牌
		-- 	cardnum = 0x0e
		-- end
		--table.insert(tbCardPoint,cardnum)

		-- if cardnum > (maxCard & 0x0f) then 
		-- 	maxCard = (tb[i] & 0xf0) + cardnum
		-- elseif cardnum == (maxCard & 0x0f) then
		-- 	-- --牌值一样，比花色
		-- 	-- if (tb[i] & 0xf0) < (maxCard & 0xf0) then 
		-- 	-- 	maxCard = (tb[i] & 0xf0) + cardnum
		-- 	-- end		
		-- end		
	end
	table.sort(tbCardNum)
	--table.sort(tbCardPoint)
	table.sort(tbCard) --从小到大
	tbRes.tbCardNum = tbCardNum
	tbRes.card = tbCard
	--豹子
	local res = self:baozi(tbCardNum)
	if res then 		
		tbRes.weight = tbWeight.baozi
		tbRes.cardType = self:getCardType(tbRes.weight)
		return tbRes		
	end
	--同花顺
	res = self:tonghuasun(tbCard,tbCardNum)
	if res then 
		tbRes.weight = tbWeight.tonghuasun
		tbRes.cardType = self:getCardType(tbRes.weight)
		return tbRes
	end		
	--同花
	res = self:tonghua(tbCard)
	if res then 
		tbRes.weight = tbWeight.tonghua
		tbRes.cardType = self:getCardType(tbRes.weight)
		return tbRes	
	end
	--顺子
	local res,isAQK = self:sunzi(tbCardNum)
	if res then 
		tbRes.weight = tbWeight.sunzi
		tbRes.isAQK = isAQk
		tbRes.cardType = self:getCardType(tbRes.weight)
		return tbRes
	end
	--对子
	res , duiziPoint = self:duizi(tbCardNum)
	if res then 
		tbRes.weight = tbWeight.duizi
		tbRes.duiziPoint = duiziPoint
		tbRes.cardType = self:getCardType(tbRes.weight)
		return tbRes
	end		
	--单张
	tbRes.weight = tbWeight.danzhang
	tbRes.cardType = self:getCardType(tbRes.weight)
	tbRes.b235 = self:special(tbCardNum)
	return tbRes
end

--取对子牌与单牌
function Rule:getDunziPoint(cardPoint)
	local card1,card2
	if cardPoint[1] == cardPoint[2] then 
		card1 = cardPoint[1]
		card2 = cardPoint[3]
	elseif cardPoint[1] == cardPoint[3] then 
		card1 = cardPoint[1]
		card2 = cardPoint[2]
	elseif cardPoint[2] == cardPoint[3] then 
		card1 = cardPoint[2]
		card2 = cardPoint[1]
	end

	return {card1,card2}
end

--比较 --单张，对子，顺子，同花，同花顺，豹子
function Rule:compareCard(res1,res2)
	if res1.b235 then 
		if res2.weight == self.tbWeight.baozi then 
			return true
		end
	end
	if res2.b235 then 
		if res1.weight == self.tbWeight.baozi then 
			return false
		end
	end
	--牌型不同
	if res1.weight > res2.weight then 
		return true
	elseif res1.weight < res2.weight then 
		return false
	end	
	--牌型相同的处理	
	local weight = res1.weight
	if weight == self.tbWeight.baozi or weight == self.tbWeight.tonghua or weight == self.tbWeight.duizi or weight == self.tbWeight.danzhang then 
		--1.豹子，同花，对子，单张，牌点从大到小A,K,Q,J,10,9,8,7,6,5,4,3,2
		local cardPoint1 = table.copy(res1.tbCardNum)
		local cardPoint2 = table.copy(res2.tbCardNum)
		--A 为最大
		for i=1,#cardPoint1 do 
			if cardPoint1[i] == 0x01 then 
				cardPoint1[i] = 0x0e 
			end
			if cardPoint2[i] == 0x01 then 
				cardPoint2[i] = 0x0e 
			end			
		end
		table.sort(cardPoint1)--从小到大
		table.sort(cardPoint2)
		--如果是对子
		if weight == self.tbWeight.duizi then 
			local card1 = self:getDunziPoint(cardPoint1)
			local card2 = self:getDunziPoint(cardPoint2)
			if card1[1] > card2[1] then
				return true
			elseif card1[1] < card2[1] then
				return false
			else
				if card1[2] > card2[2] then
					return true
				elseif card1[2] < card2[2] then
					return false
				end
				--都相等
				return false,true
			end
		end
		--一张张比大小
		for i=#cardPoint1,1,-1 do 
			if cardPoint1[i] > cardPoint2[i] then
				return true
			elseif cardPoint1[i] < cardPoint2[i] then
				return false
			end
		end
		--都相等
		return false,true
	end 
	if weight == self.tbWeight.tonghuasun or weight == self.tbWeight.sunzi then 
		--2.同花顺，顺子 QKA>JQK>10-JQ>9-10-J>8-9-10>7-8-9>6-7-8>5-6-7>4-5-6>3-4-5>2-3-4>1-2-3
		local card = res1.tbCardNum
		if res1.isAQK and not res2.isAQk then 
			return true
		elseif not res1.isAQk and res2.isAQk then 
			return false
		end
		if res1.isAQk and res2.isAQk then 
			return false,true
		end
		for i=#card,1,-1 do 
			if card[i] > res2.tbCardNum[i] then 
				return true
			elseif card[i] < res2.tbCardNum[i] then 
				return false
			end
		end
		--都相等
		return false,true
	end

end

--通过权重取牌型值
function Rule:getCardType(weight)

	local i = (weight&0xf000)/0x1000
	local text = self.tbCardType[i]
	if not text then 
		return "getCardType 错误" ..i
	end
	return i
end

function Rule:getCardTypeText(weight)
	local i = (weight&0xf000)/0x1000
	local text = self.tbCardType[i]
	if not text then 
		return "getCardType 错误" ..i
	end
	return text
end

function Rule:getCardTypeById(id)	
	local text = self.tbCardType[id]
	if not text then 
		return "getCardType 错误" ..i
	end
	return text
end

--取最大的牌
function Rule:getMaxCard(res)
	--牌型相同的处理	
	local weight = res.weight
	local cardPoint = table.copy(res.tbCardNum)
	if weight == self.tbWeight.baozi or weight == self.tbWeight.tonghua or weight == self.tbWeight.duizi or weight == self.tbWeight.danzhang then 
		--1.豹子，同花，对子，单张，牌点从大到小A,K,Q,J,10,9,8,7,6,5,4,3,2		
		--A 为最大
		for i=1,#cardPoint do 
			if cardPoint[i] == 0x01 then 
				cardPoint[i] = 0x0e 
			end
		end		
	else
	end
	table.sort(cardPoint)--从小到大		
	return cardPoint[1]
end

-- --通过权重取最大牌
-- function Rule:getMaxCard(weight)
-- 	local hua   = {"黑", "红", "梅", "方"}
-- 	local dian = {"A", "2", "3", "4", "5", "6", "7", "8", "9", "10", "J", "Q", "K"}
-- 	local we = weight & 0x00ff
-- 	local huaseNum = we & 0xf0 + 1
-- 	local dianNum = we & 0x0f
-- 	if dianNum == 0x0e then 
-- 		dianNum = 0x01
-- 	end
-- 	return hua[huaseNum]..dian[dianNum]
-- end

--取一个豹子
function Rule:getBaozi(seatRes)
	local tbCard = {}
	local tbCardIndex = {}
	local res
	local cardnum
	local tbBaozi = {
		1,14,13,12,11,10,9,8,7,6,5,4,3,2,
	}
	local card = seatRes.card
	-- local isBaozi = false
	-- if seatRes.weight == self.tbWeight.baozi then 
	-- 	isBaozi = true
	-- end

	for i,cardnum in pairs(tbBaozi) do 
		tbCardIndex = {}
		for k,v in pairs(self.tbCard) do 
			if v and cardnum == v & 0x0f then 						
				table.insert(tbCardIndex,k)
				-- self.tbCard[k] = nil			
				if #tbCardIndex == 3 then 
					break
				end
			end
		end
		if #tbCardIndex == 3 then 
			break
		end		
	end

	if #tbCardIndex == 3 then 
		for k,v in pairs(tbCardIndex) do 
			table.insert(tbCard,self.tbCard[v])
			self.tbCard[v] = nil	
		end
		--把牌放回去
		for _,v in pairs(card) do 
			table.insert(self.tbCard,v)
		end
		return tbCard
	end	
	return nil	
end



return Rule